#include "sensor/DS18B20.h"

//控制DS18B20引脚输出高低电平
void DS18B20_WriteBits(GPIO_PinState PinState)
{
    HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,PinState);
}

void DS18B20_Rst(void)	   
{                 
	DS18B20_Mode(OUT); 	                //SET OUTPUT
    DS18B20_WriteBits(GPIO_PIN_RESET); 	//拉低DO
    delay_us(480);    	                //拉低480us
    DS18B20_WriteBits(GPIO_PIN_SET); 	//拉高DO
	delay_us(30);     	                //拉高30US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void) 	   
{   
	uint8_t retry=0;
	DS18B20_Mode(IN);	//SET  INPUT	 
    // while (GPIO_ReadInputDataBit(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN)&&retry<200);
    // while (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN) == GPIO_PIN_SET && retry < 200)
	// {
	// 	retry++;
	// 	delay_us(1);
	// };	 
	// if(retry>=200)return 1;
	// else retry=0;
    // while (!GPIO_ReadInputDataBit(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN)&&retry<240);
    while (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN) == GPIO_PIN_RESET && retry < 240)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)return 1;	  
    else retry=0; 
    while (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN) == GPIO_PIN_SET && retry < 240)
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=240)return 1; 
	return 0;
}
//从DS18B20读取一个位
//返回值：1/0
uint8_t DS18B20_Read_Bit(void) 	 
{
    uint8_t data;
	DS18B20_Mode(OUT);	//SET OUTPUT
    DS18B20_WriteBits(GPIO_PIN_RESET); 
	delay_us(2);
    DS18B20_WriteBits(GPIO_PIN_SET); 
	DS18B20_Mode(IN);	//SET INPUT
	delay_us(12);
	if (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN) == GPIO_PIN_SET)
    {
        data=1;
    }
    else 
    {
        data=0;	
    } 
    delay_us(50);           
    return data;
}
//从DS18B20读取一个字节
//返回值：读到的数据
uint8_t DS18B20_Read_Byte(void)     
{        
    uint8_t i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}
//写一个字节到DS18B20
//dat：要写入的字节
void DS18B20_Write_Byte(uint8_t dat)     
 {             
    uint8_t j;
    uint8_t testb;
	DS18B20_Mode(OUT);	//SET OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_WriteBits(GPIO_PIN_RESET);	// Write 1
            delay_us(2);                            
            DS18B20_WriteBits(GPIO_PIN_SET);
            delay_us(60);             
        }
        else 
        {
            DS18B20_WriteBits(GPIO_PIN_RESET);	// Write 0
            delay_us(60);             
            DS18B20_WriteBits(GPIO_PIN_SET);
            delay_us(2);                          
        }
    }
}
//开始温度转换
void DS18B20_Start(void) 
{   						               
    DS18B20_Rst();	   
	DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0x44);	// convert
} 

//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在    	 
uint8_t DS18B20_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 设置 GPIO 端口和引脚
    GPIO_InitStruct.Pin = DS18B20_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;     // 推挽输出
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;   // 高速
    HAL_GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStruct);

    // 初始状态设为高电平（释放总线）
    HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_SET);

    // 执行 DS18B20 复位（RST）操作
    DS18B20_Rst();

    // 检测 DS18B20 是否存在并返回结果
    return DS18B20_Check();
}  

//从ds18b20得到温度值
//精度：0.1C
//返回值：温度值 （-550~1250） 
double DS18B20_Get_Temp(void)
{
    uint8_t temp;
    uint8_t TL,TH;
	double tem;
    DS18B20_Start ();  			// ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0xbe);	// convert	    
    TL=DS18B20_Read_Byte(); 	// LSB   
    TH=DS18B20_Read_Byte(); 	// MSB  
	    	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;					//温度为负  
    }else temp=1;				//温度为正	  	  
    tem=TH; 					//获得高八位
    tem*=256;    
    tem+=TL;					//获得底八位
    tem=((double)tem)*0.0625;		//转换     
	if(temp)return tem; 		//返回温度值
	else return -tem;    
}

void DS18B20_Mode(uint8_t mode)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 设置 GPIO 端口和引脚
    GPIO_InitStruct.Pin = DS18B20_GPIO_PIN;

    if (mode)
    {
        // 输出模式：推挽输出，高速
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    }
    else
    {
        // 输入模式：浮空输入
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    }

    // 初始化对应的 GPIO 引脚
    HAL_GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStruct);
}


